import createTag from '../utils/helpers/html_elements';
import AnimationItem from './AnimationItem';
import displaySync from '@ohos.graphics.displaySync'
import animator from '@ohos.animator';
import fs from '@ohos.file.fs';
import bez from '../utils/bez';
import { LogUtil } from '../utils/LogUtil'
import deviceInfo from '@ohos.deviceInfo';

/**
 * isSkipFrameByOwn需要在初始化时给出, 不能在运行时动态改变.
 * 若要支持动态改变, 需要做到动态去除displaysync的投票, 暂无合适接口.
 * 销毁后重建displaysync是个可选项, 但涉及到各种状态管理过于复杂.
 * 该场景并不常见, 故暂不实现.
 **/
const _DURATION_BY_MS_ = 20000;
const _ALLOWABLE_ERROR_BY_MS_ = 1.5; //timestamp的时间精度为1个ms, 故让容许误差稍大于该值
const Looper = function(callback, isSkipFrameByOwn) {
    this._displaySync = null;
    this._animator = null;
    this._monotonicTimeStampInMs = 0;
    this._lastAnimatorProgress = 0;
    this._lastTimestamp = 0;
    this._expectedTimestamp = 0;
    this._periodByMs = 0;
    this._callback = callback;
    this._isSkipFrameByOwn = isSkipFrameByOwn;

    if (!this._initDisplaySyncLooper()) {
        // fallback to animator
        this._initAnimatorLooper();
    }
};

Looper.prototype._skippingFrame = function (timestamp) {
    if (this._periodByMs === 0) {
        return false;
    }

    let supplyingPeriod = 0;
    if (this._lastTimestamp !== 0) {
        supplyingPeriod = timestamp - this._lastTimestamp;
    }
    this._lastTimestamp = timestamp;

    let phaseOffset = this._expectedTimestamp - timestamp;
    if ((phaseOffset < 0 && phaseOffset > -_ALLOWABLE_ERROR_BY_MS_) ||
        (phaseOffset > 0 && phaseOffset < _ALLOWABLE_ERROR_BY_MS_)) {
        phaseOffset = 0; //在容许误差范围内则忽略偏差
    }

    let halfPeriod = supplyingPeriod >> 1;
    if (phaseOffset > (halfPeriod + _ALLOWABLE_ERROR_BY_MS_)) {
        return true; //偏差离当前vsync过大, 主动跳过本帧
    }

    //计算下一帧时间戳. 注意js的取模运算与其它语言不同, 会出现负的余数
    this._expectedTimestamp = timestamp + phaseOffset % this._periodByMs + this._periodByMs;

    return false;
};

Looper.prototype._baseOnframe = function (timestamp, displaySynced) {
    if (this._isSkipFrameByOwn && this._skippingFrame(timestamp)) {
        return;
    }

    this._callback(timestamp, displaySynced);
};

Looper.prototype._baseFirst = function () {
    this._lastTimestamp = 0;
    this._expectedTimestamp = 0;
};

Looper.prototype._baseSetExpectedFrameRateRange = function (func, looperType, playingFrameRate) {
    if (func) {
        LogUtil.info(`<Looper>--lottie_ohos ${looperType} running at: ${playingFrameRate} HZ`);
        this._periodByMs = 1000 / playingFrameRate;

        if (!this._isSkipFrameByOwn) {
            // 不做投票, 避免拉低ui帧率
            func({ min: 0, max: 120, expected: playingFrameRate });
        }
    } else {
        LogUtil.info(`<Looper>--lottie_ohos ${looperType} has no displaySync. API level may be too low.`);
        this._periodByMs = 0;
    }
};

Looper.prototype._initDisplaySyncLooper = function () {
    try {
        this._displaySync = displaySync.create();
        this._displaySync.on('frame', (frameInfo) => {
            this._monotonicTimeStampInMs = ~~(frameInfo.timestamp / 1000_000); // ns to ms then truncation to integer
            this._baseOnframe(this._monotonicTimeStampInMs, true);
        });
        LogUtil.info(`<Looper>--lottie_ohos displaySync created.`);

        this._exportApiByDisplaySync();

        return true;
    } catch (e) {
        LogUtil.info(`<Looper>--lottie_ohos no displaySync. API level may be too low: ${e.message}`);
    }
    return false;
};

Looper.prototype._exportApiByDisplaySync = function() {
    //导出外部可调用方法(内部方法以"_"开头)
    this.first = function () {
        this._baseFirst();
        LogUtil.info(`<Looper>--lottie_ohos displaySync first`);
    };

    this.start = function () {
        LogUtil.info(`<Looper>--lottie_ohos displaySync start`);
        this._displaySync.start();
    };

    this.stop = function () {
        LogUtil.info(`<Looper>--lottie_ohos displaySync stop`);
        this._displaySync.stop();
    };

    this.setExpectedFrameRateRange = function (playingFrameRate) {
        this._baseSetExpectedFrameRateRange(this._displaySync.setExpectedFrameRateRange, 'displaySync',
            playingFrameRate);
    };
};

Looper.prototype._initAnimatorLooper = function () {
    let options = {
        duration: _DURATION_BY_MS_,
        easing: 'linear',
        delay: 0,
        fill: 'forwards',
        direction: 'normal',
        iterations: -1,
        begin: 0,
        end: 1
    };
    this._animator = animator.create(options);
    this._registerCallbackForAnimator();
    LogUtil.info(`<Looper>--lottie_ohos animator created.`);

    this._exportApiByAnimator();

    return true;
};

Looper.prototype._registerCallbackForAnimator = function() {
    let sdkApiVersion = deviceInfo.sdkApiVersion;

    let oncancel = () => {
        this._lastAnimatorProgress = 0;
    };
    if (sdkApiVersion >= 12) {
        this._animator.onCancel = oncancel;
    } else {
        this._animator.oncancel = oncancel;
    }

    let onfinish = () => {
        this._lastAnimatorProgress = 0;
    };
    if (sdkApiVersion >= 12) {
        this._animator.onFinish = onfinish;
    } else {
        this._animator.onfinish = onfinish;
    }

    let onframe = (progress) => {
        //在每一次帧动画回调时，忽略系统时间，仅以动画步进来计算下一次时间戳，避免时间调整引起的跳变
        let positiveProgress = progress - this._lastAnimatorProgress + 1;
        let modularProgress = positiveProgress - (~~positiveProgress);
        let step = ~~(_DURATION_BY_MS_ * modularProgress); //truncation to integer
        if (step > 0) {
            this._monotonicTimeStampInMs += step;
            this._lastAnimatorProgress = progress;
            this._baseOnframe(this._monotonicTimeStampInMs, false);
        }
    };
    if (sdkApiVersion >= 12) {
        this._animator.onFrame = onframe;
    } else {
        this._animator.onframe = onframe;
    }
};

Looper.prototype._exportApiByAnimator = function() {
    this.first = function () {
        this._baseFirst();
        this._lastAnimatorProgress = 0;
        this._monotonicTimeStampInMs = Date.now();
        LogUtil.info(`<Looper>--lottie_ohos animator first: ${this._monotonicTimeStampInMs}`);
    };

    this.start = function () {
        LogUtil.info(`<Looper>--lottie_ohos animator play`);
        this._animator.play();
    };

    this.stop = function () {
        //do not call '_animator.finish' function which will further call animator.onframe causing stack overflow.
        LogUtil.info(`<Looper>--lottie_ohos animator cancel`);
        this._animator.cancel();
    };

    this.setExpectedFrameRateRange = function (playingFrameRate) {
        this._baseSetExpectedFrameRateRange(this._animator.setExpectedFrameRateRange, 'animator', playingFrameRate);
    };
};

const animationManager = (function(){
    var moduleOb = {};
    var registeredAnimations = [];
    var playingAnimationsNum = 0;
    var _looperStopped = true;
    var _packageName = '';
    var _playingFrameRate = 0;
    var _userPlayingFrameRate = 0;
    var _looper = null;

    // web only
    function registerAnimation(element, animationData) {
        if (!element) {
            return null;
        }

        let len = registeredAnimations.length
        for (let i = 0; i < len; i++) {
            if (registeredAnimations[i]?.elem !== null && registeredAnimations[i]?.elem === element) {
                return registeredAnimations[i]?.animation;
            }
        }

        var animItem = new AnimationItem();
        setupAnimation(animItem, element);
        animItem.setData(element, animationData);
        return animItem;
    }

    // web only
    function getRegisteredAnimations() {
        var animations = [];
        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            animations.push(registeredAnimations[i]?.animation);
        }
        return animations;
    }

    function pickMaxFrameRate() {
        let maxFrameRate = 0;
        let len = registeredAnimations.length;
        for (let i = 0; i < len; i++) {
            let animItem = registeredAnimations[i]?.animation;
            if (!animItem._idle) {
                let fr = animItem.getFrameRate();
                LogUtil.info(`<${animItem.packageName}>--lottie_ohos check fr from ${animItem.name} with ${fr} fps. running fr is ${_playingFrameRate}`);
                if (fr > maxFrameRate) {
                    maxFrameRate = fr;
                }
            }
        }

        if (_userPlayingFrameRate > 0 && _userPlayingFrameRate < maxFrameRate) {
            return _userPlayingFrameRate; // user already set lower frame rate. so ignore content fr for better performance
        }

        return maxFrameRate;
    }

    function addPlayingCount() {
        playingAnimationsNum += 1;
        if (playingAnimationsNum > 0) {
            activate();
        }
    }

    function subtractPlayingCount() {
        playingAnimationsNum -= 1;
        if (playingAnimationsNum <= 0) {
            deactivate()
        }
    }

    function onAnimationItemLoaded(animItem) {
        LogUtil.info(`<${animItem.packageName}>--lottie_ohos animation created: ${animItem.name} with ${animItem.frameRate} fps`)

        _packageName = animItem.packageName;
    }

    function onAnimationItemDestroy(ev) {
        let animItem = ev.target;
        let len = registeredAnimations.length
        for (let i = len - 1; i >= 0; i--) {
            if (registeredAnimations[i]?.animation === animItem) {
                registeredAnimations[i].animation = null;
                registeredAnimations.splice(i, 1);
                LogUtil.info(`<${animItem.packageName}>--lottie_ohos animation destroyed: ${animItem.name} with ${animItem.frameRate} fps`)
            }
        }

        if (registeredAnimations.length <= 0) {
            deactivate();
        }
    }

    function onAnimationItemActive(animItem) {
        LogUtil.info(`<${animItem.packageName}>--lottie_ohos animation activated: ${animItem.name} with ${animItem.getFrameRate()} fps`)

        if (animItem.getFrameRate() > _playingFrameRate) {
            //有更高帧率的动画活动，需要刷新帧率
            let fr = pickMaxFrameRate();
            requestAnimatorFrameRateIfNeeded(fr);
        }

        addPlayingCount()
    }

    function onAnimationItemIdle(animItem) {
        LogUtil.info(`<${animItem.packageName}>--lottie_ohos animation deactivated: '${animItem.name}' with ${animItem.getFrameRate()} fps`)

        subtractPlayingCount()

        if (animItem.getFrameRate() >= _playingFrameRate) {
            //最高帧率的动画暂停，需要刷新为第二高的帧率值
            let fr = pickMaxFrameRate();
            requestAnimatorFrameRateIfNeeded(fr);
        }
    }

    function destroyOldAnimation(params) {
        let len = registeredAnimations.length;
        let node = params.container?.canvas;
        if (node) {
            let id = node.getUniqueId();
            for (let i = 0; i < len; i += 1) {
                let animation = registeredAnimations[i]?.animation;
                if (id === animation?.wrapper?.canvas?.getUniqueId()) {
                    LogUtil.info(`'${animation.packageName}-${animation.name}'--lottie_ohos destroy animations ${animation.name} from ${animation.source},
          context2D is ${id}, because animation using the same context2D. `);
                    animation.destroy();
                }
            }
        }
    }

    function setupAnimation(animItem, element) {
        animItem.addEventListener('destroy', onAnimationItemDestroy);
        animItem.addEventListener('_active', onAnimationItemActive);
        animItem.addEventListener('_idle', onAnimationItemIdle);
        animItem.addEventListener('DOMLoaded', onAnimationItemLoaded);
        registeredAnimations.push({ elem: element, animation: animItem });
    }

    function loadAnimation(params) {
        LogUtil.info(`<${params.packageName ? params.packageName : ''}>--lottie_ohos loadAnimation. ${params.name ? params.name : ''}`
            + `${params.uri ? ' from ' + params.uri : (params.path ? ' from ' + params.path : '')}`);
        destroyOldAnimation(params);
        var animItem = new AnimationItem();
        setupAnimation(animItem, null);
        animItem.setParams(params);
        return animItem;
    }

    function setSpeed(val, animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos setSpeed.${val}, ${animationName ? animationName : ''}`);
        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.setSpeed(val, animationName);
            }
        }
    }

    function setDirection(val, animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos setDirection.${val}, ${animationName ? animationName : ''}`);

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.setDirection(val, animationName);
            }
        }
    }

    function play(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos play.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.play(animationName);
            }
        }
    }

    function resume(timestamp, displaySynced) {
        let len = registeredAnimations.length;

        for (let i = 0; i < len; i += 1) {
            registeredAnimations[i]?.animation.resume(timestamp, displaySynced);
        }
    }

    function pause(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos pause.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.pause(animationName);
            }
        }
    }

    function goToAndStop(value, isFrame, animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos goToAndStop.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.goToAndStop(value, isFrame, animationName);
            }
        }
    }

    function stop(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos stop.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.stop(animationName);
            }
        }
    }

    function togglePause(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos togglePause.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.togglePause(animationName);
            }
        }
    }

    /**
     * 设置packageName
     * @param name 应用的包名
     */
    function setPackageName(name) {
        LogUtil.info(`<${_packageName}>--lottie_ohos setPackageName.${name}`);
        _packageName = name;
    }

    /**
     * 设置所有动画的最大播放帧率
     * @param frameRate 帧率
     */
    function setMaxFrameRate(frameRate) {
        LogUtil.info(`<${_packageName}>--lottie_ohos setMaxFrameRate: ${frameRate}`);
        _userPlayingFrameRate = frameRate;

        let maxFr = pickMaxFrameRate();
        requestAnimatorFrameRateIfNeeded(maxFr);
    }

    function requestAnimatorFrameRateIfNeeded(frameRate) {
        let looper = getSingletonLooper();
        if (frameRate === 0) {
            LogUtil.info(`<${_packageName}>--lottie_ohos deactivate cause framerate becomes 0.`)
            deactivate();
            return;
        }

        if (frameRate !== _playingFrameRate) {
            if (frameRate > 0 && frameRate <= 120) {
                _playingFrameRate = frameRate;
                looper.setExpectedFrameRateRange(_playingFrameRate);
            }
        }
    }

    function destroy(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos destroy.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length
        for (let i = (len - 1); i >= 0; i -= 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                //找到即将要被destroy的动画，销毁之。会触发回调，在回调中进行状态清理
                registeredAnimations[i]?.animation.destroy(animationName);
            }
        }
        if (registeredAnimations.length === 0) {
            bez.storedData = {};
        }
    }

    // html only
    function searchAnimations(animationData, standalone, renderer) {
        if (!document) {
            return;
        }
        let animElements = [].concat([].slice.call(document.getElementsByClassName('lottie')),
            [].slice.call(document.getElementsByClassName('bodymovin')));
        let lenAnims = animElements.length;
        for (let i = 0; i < lenAnims; i += 1) {
            if (renderer && !!animElements[i]) {
                animElements[i].setAttribute('data-bm-type', renderer);
            }
            registerAnimation(animElements[i], animationData);
        }
        if (standalone && lenAnims === 0) {
            if (!renderer) {
                renderer = 'svg';
            }
            var body = document.getElementsByTagName('body')[0];
            body.innerText = '';
            var div = createTag('div');
            div.style.width = '100%';
            div.style.height = '100%';
            div.setAttribute('data-bm-type', renderer);
            body.appendChild(div);
            registerAnimation(div, animationData);
        }
    }

    function setContentMode(contentMode) {
        // LogUtil.debug(`<${_packageName}>--lottie_ohos setContentMode.${contentMode}`);

        let len = registeredAnimations.length
        for (let i = 0; i < len; i += 1) {
            if (!!registeredAnimations[i]?.animation) {
                registeredAnimations[i]?.animation.setContentMode(contentMode);
            }
        }
    }

    function resize(width, height) {
        // LogUtil.debug(`<${_packageName}>--lottie_ohos resize: ${width} x ${height}`);

        let len = registeredAnimations.length
        for (let i = 0; i < len; i += 1) {
            if (!!registeredAnimations[i]?.animation) {
                registeredAnimations[i]?.animation.resize(width, height);
            }
        }
    }

    function getSingletonLooper() {
        if (!!_looper) {
            return _looper;
        }

        _looper = new Looper(resume, true);

        return _looper;
    }

    function activate() {
        if (playingAnimationsNum > 0 && _looperStopped) {

            LogUtil.info(`<${_packageName}>--lottie_ohos activate.`);
            getSingletonLooper().first();
            getSingletonLooper().start();

            _looperStopped = false;
        }
    }

    function deactivate() {
        if (!_looperStopped) {
            _looperStopped = true;
            LogUtil.info(`<${_packageName}>--lottie_ohos deactivate.`);
            _playingFrameRate = 0;
            getSingletonLooper().stop();
        }
    }

    function freeze() {
        // LogUtil.debug(`<${_packageName}>--lottie_ohos freeze.`);

        deactivate();

        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!!registeredAnimations[i]?.animation) {
                registeredAnimations[i].animation.stop();
            }
        }
    }

    function unfreeze() {
        // LogUtil.debug(`<${_packageName}>--lottie_ohos unfreeze.`);
        let len = registeredAnimations.length;
        for (let i = 0; i < len; i += 1) {
            if (!!registeredAnimations[i]?.animation) {
                registeredAnimations[i].animation.start();
            }
        }

        activate();
    }

    function setVolume(val, animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos setVolume.${val}, ${animationName ? animationName : ''}`);

        let len = registeredAnimations.length
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.setVolume(val, animationName);
            }
        }
    }

    function mute(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos mute.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.mute(animationName);
            }
        }
    }

    function unmute(animationName) {
        LogUtil.info(`<${_packageName}>--lottie_ohos unmute.${animationName ? animationName : ''}`);

        let len = registeredAnimations.length
        for (let i = 0; i < len; i += 1) {
            if (!animationName || registeredAnimations[i]?.animation.name === animationName) {
                registeredAnimations[i]?.animation.unmute(animationName);
            }
        }
    }

    function clearSingleFileCache(path, container) {
        let isHttp = path.startsWith('http');
        if (isHttp) {
            let parts = path.split('/');
            let secondLastSegment = parts[parts.length - 2];
            let lastSegmentWithExtension = parts[parts.length - 1];
            let lastSegment = lastSegmentWithExtension.replace(/\.(zip|json)$/i, '');
            let dirPath = getContext().filesDir + '/lottie';
            let dirPathFirst = `${dirPath}/${secondLastSegment}`;
            dirPath = `${dirPathFirst}/${lastSegment}`;
            rmdir(dirPath);
        }
        if (container) {
            let jsonString = container.getJsonData(path);
            let jsonObj = JSON.parse(jsonString);
            let loadPath = getContext().filesDir + '/lottie/loadImages/';
            let isExitNetworkAssets = jsonObj.assets.some((item) => {
                return item.p && item.p.startsWith('http');
            });
            if (isExitNetworkAssets) {
                rmdir(loadPath, jsonObj);
            }
        }
    }

    function clearFileCache(url, container) {
        const context = getContext();
        if (url) {
            clearSingleFileCache(url, container);
            return;
        }
        let fileDir = context.filesDir + '/lottie';
        let cacheDir = context.cacheDir + '/lottie';
        rmdir(fileDir);
        rmdir(cacheDir);
    }

    function rmAssetsDir(path, assets, filenames) {
        let isHttp = assets.p?.startsWith('http');
        if (isHttp) {
            let index = filenames.indexOf(assets.id + '.png');
            if (index !== -1) {
                fs.unlink(path + filenames[index])
                    .catch((err) => {
                        LogUtil.error(`<${_packageName}>--lottie_ohos remove file failed with error message: ${err.message} , error code: ${err.code}`);
                    });
            }
        }
    }

    function rmDirByPath(path, filename) {
        let dirPath = path + '/' + filename;
        // 判断是否文件夹
        try {
            let isDirectory = fs.statSync(dirPath).isDirectory();
            if (isDirectory) {
                fs.rmdirSync(dirPath);
            } else {
                fs.unlink(dirPath)
                    .catch((err) => {
                        LogUtil.error(`<${_packageName}>--lottie_ohos remove file failed with error message: ${err.message} , error code: ${err.code}`);
                    });
            }
        } catch (err) {
            LogUtil.error('Method rmDirByPath execute error: ' + JSON.stringify(err));
        }
    }

    function rmdir(path, jsonObj) {
        fs.listFile(path).then((filenames) => {
            if (jsonObj) {
                for (let i = 0; i < jsonObj.assets.length; i++) {
                    rmAssetsDir(path, jsonObj.assets[i], filenames);
                }
            } else {
                for (let i = 0; i < filenames.length; i++) {
                    rmDirByPath(path, filenames[i]);
                }
            }
        }).catch((err) => {
            LogUtil.error(`<${_packageName}>--lottie_ohos rmdir ${err.message}`);
        });
    }

    moduleOb.registerAnimation = registerAnimation;
    moduleOb.loadAnimation = loadAnimation;
    moduleOb.setSpeed = setSpeed;
    moduleOb.setDirection = setDirection;
    moduleOb.play = play;
    moduleOb.pause = pause;
    moduleOb.stop = stop;
    moduleOb.togglePause = togglePause;
    moduleOb.searchAnimations = searchAnimations;
    moduleOb.resize = resize;
    moduleOb.clearFileCache = clearFileCache;
    // moduleOb.start = start;
    moduleOb.goToAndStop = goToAndStop;
    moduleOb.destroy = destroy;
    moduleOb.freeze = freeze;
    moduleOb.unfreeze = unfreeze;
    moduleOb.setVolume = setVolume;
    moduleOb.mute = mute;
    moduleOb.unmute = unmute;
    moduleOb.getRegisteredAnimations = getRegisteredAnimations;
    moduleOb.setPackageName = setPackageName;
    moduleOb.setContentMode = setContentMode;
    moduleOb.setMaxFrameRate = setMaxFrameRate;
    return moduleOb;
}());

export default animationManager;
